﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using GeoUtils;
using AdvUtils;

namespace BuildGeoEntityFromMIF
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 4)
            {
                Console.WriteLine("BuildGeoEntityFromMIF [AdminCode Ontology File As Output] [Encoded Geo Entity File As Output] [MIF Files Root Path As Input] [MIF File Name Pattern:Level:Tag As Input list]");
                return;
            }

            string strDataRoot = args[2];
            string strAdminCodeOntologyDict = args[0];
            string strEncodedGeoEntityFileName = args[1];
            List<string> MIFFileNamePatternLevelTagList = new List<string>();

            for (int i = 3; i < args.Length; i++)
            {
                MIFFileNamePatternLevelTagList.Add(args[i]);
            }

            if (strDataRoot.EndsWith("\\") == false)
            {
                strDataRoot += "\\";
            }

            Dictionary<int, int> adminCode2PreCode = new Dictionary<int, int>();
            Dictionary<int, List<string>> adminCode2LocNameList = new Dictionary<int, List<string>>();
            GeoEntityBuilder builder = new GeoEntityBuilder();

            foreach (string strMIFFileNamePatternLevelTag in MIFFileNamePatternLevelTagList)
            {
                string[] items = strMIFFileNamePatternLevelTag.Split(':');
                string strFileNamePattern = items[0];
                int iLevel = int.Parse(items[1]);
                string strTag = items[2];
                string[] foundFileNameList = Directory.GetFiles(strDataRoot, strFileNamePattern, SearchOption.AllDirectories);

                foreach (string strFileName in foundFileNameList)
                {
                    using (MifReader mifReader = new MifReader(strFileName, strTag, iLevel))
                    {
                        Console.WriteLine("Process File: {0}...", strFileName);
                        List<GeoEntity> geoEntityList;
                        // Read each region from the MIF file.
                        while ((geoEntityList = mifReader.GetNextGeoEntity()) != null)
                        {
                            if (geoEntityList.Count == 0)
                            {
                                continue;
                            }

                            foreach (GeoEntity geoEntity in geoEntityList)
                            {
                                //Build admin code ontology from each geo entity
                                if (geoEntity.AdminCodeList.Count > 0)
                                {
                                    foreach (int adminCode in geoEntity.AdminCodeList)
                                    {
                                        if (adminCode == geoEntity.AdminPreCode)
                                        {
                                            continue;
                                        }
                                        if (adminCode2PreCode.ContainsKey(adminCode) == false)
                                        {
                                            adminCode2PreCode.Add(adminCode, geoEntity.AdminPreCode);
                                        }
                                        else
                                        {
                                            //Check whether admin code is validated
                                            if (geoEntity.AdminPreCode > adminCode2PreCode[adminCode])
                                            {
                                                adminCode2PreCode[adminCode] = geoEntity.AdminPreCode;
                                            }
                                        }
                                        if (adminCode2LocNameList.ContainsKey(adminCode) == false)
                                        {
                                            adminCode2LocNameList.Add(adminCode, new List<string>());
                                        }
                                        adminCode2LocNameList[adminCode].Add(geoEntity.Name);
                                    }
                                }

                                builder.AddNewGeoEntity(geoEntity, strTag);
                            }
                        }
                    }
                }
            }

            Console.WriteLine("Build Admin Code Ontology...");
            StreamWriter swAdminCodeOntology = new StreamWriter(strAdminCodeOntologyDict);
            foreach (KeyValuePair<int, int> pair in adminCode2PreCode)
            {
                if (adminCode2LocNameList[pair.Key].Count == 1)
                {
                    swAdminCodeOntology.WriteLine("{0}\t{1}\t{2}", pair.Key, pair.Value, adminCode2LocNameList[pair.Key][0]);
                }
                else
                {
                    swAdminCodeOntology.WriteLine("{0}\t{1}", pair.Key, pair.Value);
                }
            }
            swAdminCodeOntology.Close();

            Console.WriteLine("Build Geo Entities...");
            builder.Build(strEncodedGeoEntityFileName);

            Console.WriteLine("Build Successed.");
        }
    }
}
